package com.rf.sys.shiro.credentials;

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.util.ByteSource;

import java.util.concurrent.atomic.AtomicInteger;


public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher {
    private Cache<String, AtomicInteger> passwordRetryCache;

    public RetryLimitHashedCredentialsMatcher(CacheManager cacheManager) {
        passwordRetryCache = cacheManager.getCache("passwordRetryCache");
    }

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token,AuthenticationInfo info) {
        String username = (String) token.getPrincipal();

        //获取缓存中的密码重试次数
        AtomicInteger retryCount = passwordRetryCache.get(username);
        //判断重试次数是否存在
        if (retryCount == null) {
        	//设置重试次数+1
            retryCount = new AtomicInteger(0);
            passwordRetryCache.put(username, retryCount);
        }
        //判断是否重试次数大于5
        if (retryCount.incrementAndGet() > 5) {
            //提示重试次数过多
            throw new ExcessiveAttemptsException();
        }

        //匹配用户输入的token 的凭证（未加密）与系统提供的凭证（已加密）
        boolean matches = super.doCredentialsMatch(token, info);
        //判断匹配是否成功
        if (matches) {
            //清空重试缓存
            passwordRetryCache.remove(username);
        }
        return matches;
    }
	
	/**
	* build user password
	*/
	public String buildCredentials(String userName, String password,String credentialsSalt) {
		SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(userName,password,ByteSource.Util.bytes(userName + credentialsSalt),userName);
		AuthenticationToken token = new UsernamePasswordToken(userName, password);
		return super.hashProvidedCredentials(token, authenticationInfo).toString();
    }
}
